package com.yehebl.orm.check;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class EntityClass {
	static Map<String, String>  maps = new HashMap<>();
	static Map<String, String> mapPacks = new HashMap<>();
	static {
		maps.put("VARCHAR", "String");
		maps.put("CHAR", "String");
		maps.put("BLOB", "byte[]");
		maps.put("VARBINARY", "byte[]");
		maps.put("TEXT", "String");
		maps.put("LONGTEXT", "String");
		maps.put("INTEGER", "Integer");
		maps.put("INT", "Integer");
		maps.put("TINYINT", "Integer");
		maps.put("SMALLINT", "Integer");
		maps.put("MEDIUMINT", "Integer");
		maps.put("MEDIUMTEXT", "String");
		maps.put("BIT", "Boolean");
		maps.put("BIGINT", "Long");
		maps.put("FLOAT", "Float");
		maps.put("DOUBLE", "Double");
		maps.put("DECIMAL", "BigDecimal");
		maps.put("BOOLEAN", "Integer");
		maps.put("ID", "Long");
		maps.put("DATE", "Date");
		maps.put("TIME", "Date");
		maps.put("DATETIME", "Date");
		maps.put("YEAR", "Date");
		maps.put("TIMESTAMP", "Date");
		
		mapPacks.put("MEDIUMTEXT", "java.lang.String");
		mapPacks.put("LONGTEXT", "java.lang.String");
		mapPacks.put("VARCHAR", "java.lang.String");
		mapPacks.put("CHAR", "java.lang.String");
		mapPacks.put("BLOB", "java.lang.byte");
		mapPacks.put("VARBINARY", "java.lang.byte");
		mapPacks.put("TEXT", "java.lang.String");
		mapPacks.put("INTEGER", "java.lang.Integer");
		mapPacks.put("INT", "java.lang.Integer");
		mapPacks.put("TINYINT", "java.lang.Integer");
		mapPacks.put("SMALLINT", "java.lang.Integer");
		mapPacks.put("MEDIUMINT", "java.lang.Integer");
		mapPacks.put("BIT", "java.lang.Boolean");
		mapPacks.put("BIGINT", "java.lang.Long");
		mapPacks.put("FLOAT", "java.lang.Float");
		mapPacks.put("DOUBLE", "java.lang.Double");
		mapPacks.put("DECIMAL", "java.math.BigDecimal");
		mapPacks.put("BOOLEAN", "java.lang.Integer");
		mapPacks.put("ID", "java.lang.Long");
		mapPacks.put("DATE", "java.util.Date");
		mapPacks.put("TIME", "java.util.Date");
		mapPacks.put("DATETIME", "java.util.Date");
		mapPacks.put("YEAR", "java.util.Date");
		mapPacks.put("TIMESTAMP", "java.util.Date");
	}
	public static ClassAuto generateEntityClass(String msg) {
		ClassAuto ca = new ClassAuto();
		// 1.将Sql语句转换成小写
		String sql = msg.toLowerCase();
		String initSql=sql;
		// 2.将'全部去掉
		sql = sql.replaceAll("`", "");
		// 3.检索(出现的位置
		int zIndex = sql.indexOf("(");
		// 4.返回指定字符串值最后出现的问题，在一个字符串中的指定位置从后向前检索
		int yIndex = sql.lastIndexOf("\n)");

		// 6.截取)之前的字符
		String lastSql = sql.substring(yIndex);
		sql = sql.substring(zIndex + 1, yIndex);
		// 10.处理表中的内容
		String tableDesc = null;
		// 11.得到字段备注的位置
		int tableDescIndex = lastSql.indexOf("comment='");
		if (tableDescIndex != -1) {
			// 截取comment=''之间的值
			tableDesc = lastSql.substring(tableDescIndex + "comment='".length(), lastSql.lastIndexOf("'"));
		} else {
			// 对没有等号之间的值
			tableDescIndex = lastSql.indexOf("comment '");
			if (tableDescIndex != -1) {
				tableDesc = lastSql.substring(tableDescIndex + "comment '".length(), lastSql.lastIndexOf("'"));
			}
		}
		// 截取换行的字符
		String[] sqls = sql.split("\n");
		String [] initSqls=initSql.split("\n");
		Set<String> tableIdSet=new HashSet<>();
		List<String> childPack = new ArrayList<>();
		for (int i = 0; i < sqls.length; i++) {
			if (sqls[i] == null || sqls[i].trim().equals("")) {
				continue;
			}
			// 得到主键的id
			if (sqls[i].contains("primary key")) {
				ca.setTableId(true);
				tableIdSet.add(conv(((sqls[i].substring(sqls[i].indexOf("(")+1, sqls[i].indexOf(")"))).trim()),false));
				continue;
			}
			// 当有key时不执行
			if (sqls[i].contains(" key ") && !initSqls[i].contains(" `key` ")) {
				continue;
			}
			// 当有unique key时不执行
			 if(sqls[i].contains(" unique key ") && !initSqls[i].contains(" `unique key` ")){
				 continue;
             }
			FieldAuto fieldAuto = new FieldAuto();
			sqls[i] = sqls[i].trim();
			if (sqls[i].contains(" comment ") && sqls[i].contains("'")) {
				String[] contentVal = sqls[i].split(" comment ");
				// 得到''中的数据
				fieldAuto.setDesc(contentVal[1].substring(contentVal[1].indexOf("'")+1, contentVal[1].lastIndexOf("'")));
			}
			String[] sqlArray;
			
			if (!sqls[i].contains("'")) {
				sqlArray = sqls[i].split(" ");
			} else {
				sqlArray = sqls[i].substring(0, sqls[i].indexOf("'")).split(" ");
			}
			int tk = 0;
			for (String s : sqlArray) {
				if (!"".equals(s)) {
					if (tk == 0) {
						fieldAuto.setFieldName(conv(s, false));
					} else if (tk == 1) {
						String type;
						if (s.contains("(")) {
							type = s.substring(0, s.indexOf("("));
						} else {
							type = s;
						}
						fieldAuto.setType(getMysqlTypeMap(type.toUpperCase()));
						if (getMysqlTypePack(type.toUpperCase()) != null) {
							childPack.add(getMysqlTypePack(type.toUpperCase()));
						}
					}
					tk += 1;
				}
			}
			ca.getFieldList().add(fieldAuto);
		}
		Set<String> setPack = new HashSet<>();
		for (String s : childPack) {
			if (!setPack.contains(s)) {
				ca.getPackList().add(s);
			}
			setPack.add(s);
		}
		for (FieldAuto fa:ca.getFieldList()) {
			for (String tableId:tableIdSet) {
				if(tableId.equals(fa.getFieldName())) {
					fa.setId(true);
					break;
				}
			}
		}
		ca.setClassDesc(tableDesc);
		return ca;
	}

	/**
	 * 将表名转换成类名
	 */
	public static String conv(String str, boolean flag) {
		StringBuilder header = new StringBuilder();
		// 1.
		if (str == null || str.equals("")) {
			return header.toString();
		}
		// 已下划线分隔成两个字符保存到字符串数组中
		String[] headerArray = str.split("_");
		for (int i = 0; i < headerArray.length; i++) {
			// 将首字母转换成大写
			if (i > 0) {
				header.append(headerArray[i].substring(0, 1).toUpperCase());
				// 获取表名后面的字符并转换成小写
				header.append(headerArray[i].substring(1).toLowerCase());
			} else {
				if (flag) {
					header.append(headerArray[i].substring(0, 1).toUpperCase());
					// 获取表名后面的字符并转换成小写
					header.append(headerArray[i].substring(1).toLowerCase());
				} else {
					header.append(headerArray[i].toLowerCase());
				}
			}

		}
		return header.toString();
	}

	public static String getMysqlTypeMap(String key) {
		return maps.get(key);
	}

	public static String getMysqlTypePack(String key) {
		return mapPacks.get(key);
	}

}

class Child {

	private String name;

	private String column;

	private String content;

	private String type;

	private String set;

	private String get;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getColumn() {
		return column;
	}

	public void setColumn(String column) {
		this.column = column;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getSet() {
		return set;
	}

	public void setSet(String set) {
		this.set = set;
	}

	public String getGet() {
		return get;
	}

	public void setGet(String get) {
		this.get = get;
	}

}
